package io.ouka.jvm.hotspot.selfread.read;

import io.ouka.jvm.hotspot.selfread.InstanceKlass;
import io.ouka.jvm.hotspot.selfread.constant.FinalConstant;
import io.ouka.jvm.hotspot.selfread.domain.InterfaceInfo;
import io.ouka.jvm.hotspot.selfread.util.DataTranslate;

import java.util.ArrayList;
import java.util.List;

/**
 * @author ouka
 * ClassDetailReader
 */
public class ParentAndInterfaceDetailReader extends AbstractReader{

    public ParentAndInterfaceDetailReader() {
        this.iReader = new FieldsReader();
    }

    private byte[] className;
    private byte[] parentClass;
    private int interfaceNums;
    private byte[] interfaces;
    @Override
    public void preRead(byte[] content) {

        System.arraycopy(content,index, FinalConstant.U2BYTE,0,FinalConstant.u2);
        this.className = FinalConstant.U2BYTE;
        index+=FinalConstant.u2;

        System.arraycopy(content,index, FinalConstant.U2BYTE,0,FinalConstant.u2);
        this.parentClass = FinalConstant.U2BYTE;
        index+=FinalConstant.u2;

        System.arraycopy(content,index, FinalConstant.U2BYTE,0,FinalConstant.u2);
        this.interfaceNums = DataTranslate.byteToUnsignedShort(FinalConstant.U2BYTE);
        index+=FinalConstant.u2;
        if (interfaceNums==0) return ;
        byte[] bytes = new byte[FinalConstant.u2*interfaceNums];
        System.arraycopy(content,index, bytes,0,FinalConstant.u2*interfaceNums);
        this.interfaces = bytes;
        index+=FinalConstant.u2*interfaceNums;

    }

    @Override
    public void read() {
        instanceKlass.setClassName(DataTranslate.byteToUnsignedShort(className));
        instanceKlass.setParentClassName(DataTranslate.byteToUnsignedShort(parentClass));
        instanceKlass.setInterfaceNums(interfaceNums);
        if (interfaceNums==0) return ;
        parseInterfaces(instanceKlass);
    }

    private void parseInterfaces(InstanceKlass instanceKlass) {
        List<InterfaceInfo> list = new ArrayList<>(interfaceNums);
        int interfaceBytesReadIndex = 0;
        for (int i = 0; i < interfaceNums; i++) {
            System.arraycopy(interfaces,interfaceBytesReadIndex,FinalConstant.U2BYTE,0,FinalConstant.u2);
            interfaceBytesReadIndex+=FinalConstant.u2;
            int constantPoolIndex = DataTranslate.byteToUnsignedShort(FinalConstant.U2BYTE);
            String interfaceName = instanceKlass.getConstantPool().getClassName(constantPoolIndex);
            InterfaceInfo interfaceInfo = new InterfaceInfo(i, interfaceName);
            list.add(interfaceInfo);
        }
        instanceKlass.setInterfaceInfos(list);
    }
}
